#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <map>
#include <list>
#include <functional>
#include <stdint.h>
#include <string>
#include <boost/function.hpp>
#include <boost/asio.hpp>
#include "TcpNet.h"

using namespace std;



namespace boost{
    namespace asio{
    class io_service;
    };
};

class ClientHost;

typedef boost::function< bool ( ClientHost*, const std::string &) > HostCallback;


struct HostObj{
    HostObj(HostCallback callback, std::string & sendMsg):
        callback_(callback)
        ,sendmsg_(sendMsg){

        }
    HostCallback callback_;
    std::string sendmsg_;
};

class ClientHost{
    struct Impl;
    Impl *impl_;

    //void mainThreadRun();
    friend class TcpServer;

    ClientHost(boost::asio::ip::tcp::socket* sock);
    ~ClientHost();

	void setConnnected(bool flag);
public:

	boost::asio::ip::tcp::endpoint getEndpoint();
	boost::asio::ip::tcp::socket& getScoket();
    void addAsyncRequest( HostCallback callback, std::string& data);
	void addAsyncSend(  std::string& data);
    void addListener( HostCallback callback);
    bool isConn();
    void close();
};


class TcpServer
{

    static  TcpServer* inst;
    TcpServer();


    struct Impl;
    Impl* impl_;
    friend class ClientHost;
    int port_;

public:
    ~TcpServer();
    static TcpServer *instance();
    void startThread();
    virtual void runMain();
    void stop();

    void threadRun();

    void setPort(int port){ port_ = port;}
    bool hasHost(const std::string &ip);
    ClientHost* getHost(const  std::string &ip);
    //ClientHost* createHost(const  std::string &ip);//return the one found if already there
    bool removeHost(const  std::string &ip);

	void startAccept();

    boost::asio::io_service * getMainService();
    boost::asio::io_service * getScoketService();

	void addBasicListener(HostCallback callback);
};




#endif // TCPSERVER_H
